home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / inventor / www / workarounds / DetailLeak1.0.C next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  10.5 KB  |  428 lines

  1. #include <Inventor/SoPath.h>
  2. #include <Inventor/actions/SoSearchAction.h>
  3. #include <Inventor/nodes/SoSeparator.h>
  4. #include <Inventor/nodes/SoCoordinate3.h>
  5. #include <Inventor/nodes/SoNormal.h>
  6. #include <Inventor/SoDetail.h>
  7.  
  8. //
  9. // Several methods of SoDetail subclasses call an internal routine
  10. // that creates a SoSearchAction but fails to delete it.  This causes
  11. // a large memory leak (the searchAction, all of the paths it finds,
  12. // and all of the nodes on those paths will never be deleted) and will
  13. // cause the application to slow down because of the extra paths.
  14. //
  15. // To fix this, compile this file into a .o and then link
  16. // the .o before -lInventor_s.  The linker will give warnings like:
  17. // Warning: getCoordinate3Node__19SoVertexShapeDetailCFv: multiply defined
  18. //        previous (used) definition from 'detail.o';
  19. //        new (ignored) definition from '/usr/lib/libInventor_s.a'
  20. // This is normal and expected.
  21. //
  22.  
  23.  
  24. ////////////////////////////////////////////////////////////////////////
  25. //
  26. // Description:
  27. //    Return the coordinate node that affects this shape.
  28. //
  29. // Use: protected
  30.  
  31. SoCoordinate3 *
  32. SoVertexShapeDetail::getCoordinate3Node() const
  33. //
  34. ////////////////////////////////////////////////////////////////////////
  35. {
  36.     return
  37.       (SoCoordinate3 *) getLastPropertyNode(SoCoordinate3::getClassTypeId());
  38. }
  39.  
  40. ////////////////////////////////////////////////////////////////////////
  41. //
  42. // Description:
  43. //    Return the normal node that affects this shape, NULL if
  44. // there isn't one.
  45. //
  46. // Use: protected
  47.  
  48. SoNormal *
  49. SoVertexShapeDetail::getNormalNode() const
  50. //
  51. ////////////////////////////////////////////////////////////////////////
  52. {
  53.     return
  54.       (SoNormal *) getLastPropertyNode(SoNormal::getClassTypeId());
  55. }
  56.  
  57. ////////////////////////////////////////////////////////////////////////
  58. //
  59. // Description:
  60. //  Returns the node of the given type that affects the shape that
  61. //  this detail's path leads to. The passed property node should
  62. //  be one that does not accumulate such as, oh, gosh,
  63. //  maybe a Normal or a Coordinate3 node, because we look
  64. //  for the last (and hence current) one.
  65. //
  66. //
  67. // Use: private
  68.  
  69. SoNode *
  70. SoVertexShapeDetail::getLastPropertyNode(SoType typeId) const
  71. //
  72. ////////////////////////////////////////////////////////////////////////
  73. {
  74. #ifdef DEBUG    
  75.     if (path == NULL) {
  76.      fprintf( stderr, "SoVertexShapeDetail::getLastPropertyNode - " );
  77.      fprintf( stderr, "path to shape is NULL\n" );
  78.      return NULL;
  79.     }
  80. #endif
  81.  
  82.     SoNode *result;
  83.     
  84.     if (path->getTail()->isOfType(typeId)) {
  85.     // path already leads to a node of given type, so just return it
  86.     result = path->getTail();
  87.     }
  88.     else {
  89.     // Apply a search action to the path, and look
  90.     // for the _last_ node of the requested type
  91.     
  92.     SoSearchAction sa;
  93.     sa.setType(typeId);
  94.     sa.setFindAll(TRUE);
  95.     sa.apply(path);
  96.  
  97.     SoPathList paths = sa.getPaths();
  98.     
  99.     if (paths.length() == 0) {
  100.         // nothing found
  101.         result = NULL;
  102.     }
  103.     else {
  104.         // return the last one found
  105.         result = paths[paths.length() - 1]->getTail();
  106.     }
  107.     }
  108.  
  109.     return result;
  110. }
  111.  
  112. ////////////////////////////////////////////////////////////////////////
  113. //
  114. // Description:
  115. //    Return the point detail information.
  116. //
  117. // Use: public
  118.  
  119. void
  120. SoPointDetail::getPoint(
  121.     long &_coordIndex, SoCoordinate3 *&coordNode,
  122.     long &_normalIndex, SoNormal *&normalNode) const
  123.  
  124. //
  125. ////////////////////////////////////////////////////////////////////////
  126. {
  127.     _coordIndex = coordIndex;
  128.     _normalIndex = normalIndex;
  129.  
  130.     coordNode = getCoordinate3Node();
  131.     if (normalIndex == SO_DETAIL_NO_NORMAL_NODE)
  132.     normalNode = NULL;
  133.     else
  134.     normalNode = getNormalNode();
  135. }
  136.  
  137. ////////////////////////////////////////////////////////////////////////
  138. //
  139. // Description:
  140. //    Return the line detail information.
  141. //
  142. // Use: public
  143.  
  144. void
  145. SoLineDetail::getLine(
  146.     long &_coordIndex0, long &_coordIndex1, 
  147.     SoCoordinate3 *&coordNode,
  148.     long &_normalIndex0, long &_normalIndex1, 
  149.     SoNormal *&normalNode) const
  150. //
  151. ////////////////////////////////////////////////////////////////////////
  152. {
  153.     _coordIndex0 = coordIndex0;
  154.     _coordIndex1 = coordIndex1;
  155.  
  156.     _normalIndex0 = normalIndex0;
  157.     _normalIndex1 = normalIndex1;
  158.  
  159.     coordNode = getCoordinate3Node();
  160.  
  161.     if (normalIndex0 == SO_DETAIL_NO_NORMAL_NODE)
  162.     normalNode = NULL;
  163.     else        
  164.     normalNode = getNormalNode();
  165. }
  166.  
  167. ////////////////////////////////////////////////////////////////////////
  168. //
  169. // Description:
  170. //    return the detail about the closest point
  171. //
  172. // Use: virtual public
  173.  
  174. const SoPointDetail &
  175. SoLineDetail::getClosestPoint()
  176. {
  177.     long closeCoordIndex;
  178.     long closeNormalIndex;
  179.     
  180.     SoCoordinate3 *coordNode = getCoordinate3Node();
  181.  
  182.     float dist0 = (point - coordNode->point[(int) coordIndex0]).length();
  183.     float dist1 = (point - coordNode->point[(int) coordIndex1]).length();
  184.  
  185.     if (dist0 < dist1) {
  186.     closeCoordIndex = coordIndex0;
  187.     closeNormalIndex = normalIndex0;
  188.     }
  189.     else {
  190.     closeCoordIndex = coordIndex1;
  191.     closeNormalIndex = normalIndex1;
  192.     }
  193.  
  194.     pointDetail.setPointCoordinate(closeCoordIndex);
  195.     pointDetail.setPoint(coordNode->point[(int) closeCoordIndex]);
  196.     
  197.     if (closeNormalIndex == SO_DETAIL_NO_NORMAL_NODE) {
  198.     pointDetail.setNormal(normal);
  199.     }
  200.     else {
  201.     pointDetail.setPointNormal(closeNormalIndex);
  202.     
  203.     SoNormal *normalNode = getNormalNode();
  204.     if (normalNode)
  205.         pointDetail.setNormal(normalNode->vector[(int) closeNormalIndex]);
  206.     else
  207.         pointDetail.setNormal(normal);
  208.     }
  209.     
  210.     pointDetail.setPath(path);
  211.     pointDetail.setMatrix(objToWorld);
  212.     pointDetail.setUnits(unitsType);
  213.  
  214.     return pointDetail;
  215. }
  216.  
  217. ////////////////////////////////////////////////////////////////////////
  218. //
  219. // Description:
  220. //    Return the line detail information.
  221. //
  222. // Use: public
  223.  
  224. void
  225. SoFaceDetail::getFace(
  226.     long &_numCoords, long *&_coordIndexList,
  227.     SoCoordinate3 *&coordNode,
  228.     long &_numNormals, long *&_normalIndexList,
  229.     SoNormal *&normalNode) const
  230. //
  231. ////////////////////////////////////////////////////////////////////////
  232. {
  233.     _numCoords = numCoords;
  234.     _coordIndexList = coordIndexList;
  235.     _numNormals = numNormals;
  236.     _normalIndexList = normalIndexList;
  237.  
  238.     coordNode = getCoordinate3Node();
  239.  
  240.     if (numNormals == SO_DETAIL_NO_NORMAL_NODE)
  241.     normalNode = NULL;
  242.     else        
  243.     normalNode = getNormalNode();
  244. }
  245.  
  246. ////////////////////////////////////////////////////////////////////////
  247. //
  248. // Description:
  249. //    return the detail about the closest point
  250. //
  251. // Use: virtual public
  252.  
  253. const SoPointDetail &
  254. SoFaceDetail::getClosestPoint()
  255. {
  256.     SoCoordinate3 *coordNode = getCoordinate3Node();
  257.  
  258.     float minDist = (point -coordNode->point[(int)coordIndexList[0]]).length();
  259.     long closeCoordIndex = 0;
  260.     long closeNormalIndex = 0;
  261.  
  262.     for (int i = 1; i < numCoords; i++) {
  263.     float dist = 
  264.         (point - coordNode->point[(int)coordIndexList[i]]).length();
  265.  
  266.     if (dist < minDist) {
  267.         minDist = dist;
  268.         closeCoordIndex = i;
  269.  
  270.         if (numNormals != 1)
  271.         closeNormalIndex = i;
  272.     }
  273.     }
  274.     
  275.     pointDetail.setPointCoordinate(coordIndexList[closeCoordIndex]);
  276.     pointDetail.setPoint(coordNode->point[
  277.              (int)coordIndexList[closeCoordIndex]]);
  278.     
  279.     if (numNormals == SO_DETAIL_NO_NORMAL_NODE) {
  280.     pointDetail.setNormal(normal);
  281.     }
  282.     else {
  283.     pointDetail.setPointNormal(normalIndexList[closeNormalIndex]);
  284.     
  285.     SoNormal *normalNode = getNormalNode();
  286.     if (normalNode)
  287.         pointDetail.setNormal(
  288.         normalNode->vector[(int)normalIndexList[closeNormalIndex]]);
  289.     else
  290.         pointDetail.setNormal(normal);
  291.         
  292.     }
  293.     
  294.     pointDetail.setPath(path);
  295.     pointDetail.setMatrix(objToWorld);
  296.     pointDetail.setUnits(unitsType);
  297.  
  298.     return pointDetail;
  299. }
  300.  
  301. ////////////////////////////////////////////////////////////////////////
  302. //
  303. // Description:
  304. //    return the detail about the closest line
  305. //
  306. // Use: virtual public
  307.  
  308. const SoLineDetail &
  309. SoFaceDetail::getClosestLine()
  310. {
  311.     
  312.     SoCoordinate3 *coordNode = getCoordinate3Node();
  313.  
  314.     // Start with the edge that goes from the last to the first point
  315.     SbLine edge(
  316.     coordNode->point[(int)coordIndexList[numCoords - 1]],
  317.     coordNode->point[(int)coordIndexList[0]]);
  318.  
  319.     SbVec3f closePoint = edge.getClosestPoint(point);
  320.     float minDist = (point - closePoint).length();
  321.     long closeCoordIndex = numCoords - 1;
  322.  
  323.     for (int i = 0; i < numCoords - 1; i++) {
  324.     edge.setValue(
  325.         coordNode->point[(int)coordIndexList[i]],
  326.         coordNode->point[(int)coordIndexList[i+1]]);
  327.  
  328.     SbVec3f edgePoint = edge.getClosestPoint(point);
  329.     float dist = (point - edgePoint).length();
  330.  
  331.     if (dist < minDist) {
  332.         minDist = dist;
  333.         closePoint = edgePoint;
  334.         closeCoordIndex = i;
  335.     }
  336.     }
  337.  
  338.     // Fill the the coordinate indices for the detail
  339.     long c0, c1, n0, n1; // indices of the coord and normal
  340.     
  341.     if (closeCoordIndex == numCoords - 1) {
  342.     c0 = coordIndexList[numCoords - 1];
  343.     c1 = coordIndexList[0];
  344.     }
  345.     else {
  346.     c0 = coordIndexList[closeCoordIndex];
  347.     c1 = coordIndexList[closeCoordIndex + 1];
  348.     }
  349.  
  350.     // Indices of the coordinates
  351.     lineDetail.setLineCoordinates(c0, c1);
  352.     
  353.     // Set the detail point to be the close point on the edge    
  354.     lineDetail.setPoint(closePoint);
  355.  
  356.     // Fill in the normal indices for the detail
  357.     if (numNormals == SO_DETAIL_NO_NORMAL_NODE) {
  358.     n0 = n1 = SO_DETAIL_NO_NORMAL_NODE;
  359.     }
  360.     else {
  361.     if (numNormals == 1) {
  362.         // Overall
  363.         n0 = n1 = 0;
  364.     }
  365.     else {
  366.         // Per vertex
  367.         if (closeCoordIndex == numCoords - 1) {
  368.         n0 = normalIndexList[closeCoordIndex - 1];
  369.         n1 = normalIndexList[0];
  370.         }
  371.         else {
  372.         n0 = normalIndexList[closeCoordIndex];
  373.         n1 = normalIndexList[closeCoordIndex + 1];
  374.         }
  375.  
  376.     }
  377.     }
  378.  
  379.     lineDetail.setLineNormals(n0, n1);
  380.     
  381.     // Fill in the normal for the detail point.
  382.     SbVec3f edgeNormal; // the normal at the closePoint on the edge
  383.  
  384.     if (numNormals == SO_DETAIL_NO_NORMAL_NODE) {
  385.     // Default normal
  386.     edgeNormal = normal;    
  387.     }
  388.     else {
  389.     SoNormal *normalNode = getNormalNode();
  390.  
  391.     if (! normalNode) {
  392.         edgeNormal = normal;
  393.     }
  394.     else {
  395.         if (numNormals == 1) {
  396.         // Overall
  397.         edgeNormal = normalNode->vector[(int) normalIndexList[0]];
  398.         }
  399.         else {
  400.         // Per vertex
  401.         // Interpolate the normal along the edge
  402.  
  403.         SbVec3f norm0, norm1, coord0, coord1;
  404.  
  405.         coord0 = coordNode->point[(int)c0];
  406.         coord1 = coordNode->point[(int)c1];
  407.  
  408.         norm0 = normalNode->vector[(int)n0];
  409.         norm1 = normalNode->vector[(int)n1];
  410.  
  411.         float dist0 = (closePoint - coord0).length();
  412.         float dist = (coord1 - coord0).length();
  413.  
  414.         edgeNormal = norm0 + (dist0/dist) * (norm1 - norm0);
  415.         }
  416.     }
  417.     }
  418.     
  419.     lineDetail.setNormal(edgeNormal);
  420.  
  421.     // This stuff doesn't change.    
  422.     lineDetail.setPath(path);
  423.     lineDetail.setMatrix(objToWorld);
  424.     lineDetail.setUnits(unitsType);
  425.  
  426.     return lineDetail;
  427. }
  428.